import { Collision } from '../collision/Collision';
import { Node, Label, Layers, PhysicsSystem, PhysicsSystem2D, Sprite, Color, tween, Vec3 } from 'cc';
import { Vector2, Vector3 } from '../utils/Math';
// 假设有PhysicsObject组件
// import { PhysicsObject } from '../modelScript/PhysicsObject';

/**
 * 统一碰撞测试用例，节点可视化、自动运动、碰撞高亮
 */
export class CollisionTest {
    static runAll(parentNode?: Node) {
        this.testCircleCircle(parentNode);
        this.testRectRect(parentNode);
        this.testPolygonPolygon(parentNode);
        this.testBatchCircle(parentNode);
        this.testSphereSphere(parentNode);
        this.testBoxBox(parentNode);
        this.testTriangleTriangle(parentNode);
        this.testPolyhedronPolyhedron(parentNode);
        this.testBatchSphere(parentNode);
    }
    /** 2D圆形碰撞测试（节点可视化+缓动） */
    static testCircleCircle(parentNode?: Node) {
        if (PhysicsSystem2D && !PhysicsSystem2D.instance.enable) PhysicsSystem2D.instance.enable = true;
        const nodeA = new Node('CircleA');
        const nodeB = new Node('CircleB');
        nodeA.layer = nodeB.layer = Layers.Enum.UI_2D;
        nodeA.setPosition(-100, 0); nodeB.setPosition(100, 0);
        const labelA = nodeA.addComponent(Label); labelA.string = 'A';
        const labelB = nodeB.addComponent(Label); labelB.string = 'B';
        labelA.fontSize = labelB.fontSize = 24;
        labelA.color = labelB.color = Color.GREEN;
        if (parentNode) { parentNode.addChild(nodeA); parentNode.addChild(nodeB); }
        const r1 = 30, r2 = 30;
        tween(nodeB)
          .to(2, { position: new Vec3(-100, 0, 0) }, {
            onUpdate: () => {
                const hit = Collision.circleCircle(
                    new Vector2(nodeA.position.x, nodeA.position.y), r1,
                    new Vector2(nodeB.position.x, nodeB.position.y), r2
                );
                labelA.color = labelB.color = hit ? Color.RED : Color.GREEN;
            }
          })
          .call(() => {
            nodeA.removeFromParent(); nodeB.removeFromParent();
          })
          .start();
    }
    /** 2D矩形碰撞测试（节点可视化+缓动） */
    static testRectRect(parentNode?: Node) {
        if (!parentNode) return;
        parentNode.removeAllChildren();
        const nodeA = new Node('RectA');
        const nodeB = new Node('RectB');
        nodeA.layer = nodeB.layer = Layers.Enum.UI_2D;
        nodeA.setPosition(-60, 0); nodeB.setPosition(60, 0);
        const labelA = nodeA.addComponent(Label); labelA.string = 'RectA';
        const labelB = nodeB.addComponent(Label); labelB.string = 'RectB';
        labelA.fontSize = labelB.fontSize = 18;
        labelA.color = labelB.color = Color.GREEN;
        parentNode.addChild(nodeA); parentNode.addChild(nodeB);
        // 缓动B节点
        const width = 60, height = 40;
        let hit = false;
        const update = () => {
            const a = new Vector2(nodeA.position.x, nodeA.position.y);
            const b = new Vector2(nodeB.position.x, nodeB.position.y);
            hit = Collision.rectRect(a, width, height, b, width, height);
            labelA.color = labelB.color = hit ? Color.RED : Color.GREEN;
        };
        tween(nodeB)
            .to(2, { position: nodeA.position.clone() }, { onUpdate: update })
            .call(() => {
                nodeA.removeFromParent(); nodeB.removeFromParent();
            })
            .start();
        update();
        this._show(parentNode, '2D矩形碰撞', true);
    }
    /** 2D多边形碰撞测试（节点可视化+缓动） */
    static testPolygonPolygon(parentNode?: Node) {
        if (!parentNode) return;
        parentNode.removeAllChildren();
        const nodeA = new Node('PolyA');
        const nodeB = new Node('PolyB');
        nodeA.layer = nodeB.layer = Layers.Enum.UI_2D;
        nodeA.setPosition(-40, 0); nodeB.setPosition(40, 0);
        const labelA = nodeA.addComponent(Label); labelA.string = 'PolyA';
        const labelB = nodeB.addComponent(Label); labelB.string = 'PolyB';
        labelA.fontSize = labelB.fontSize = 18;
        labelA.color = labelB.color = Color.GREEN;
        parentNode.addChild(nodeA); parentNode.addChild(nodeB);
        // 缓动B节点
        let hit = false;
        const update = () => {
            const triA = [new Vector2(nodeA.position.x, nodeA.position.y), new Vector2(nodeA.position.x+20, nodeA.position.y), new Vector2(nodeA.position.x+10, nodeA.position.y+30)];
            const triB = [new Vector2(nodeB.position.x, nodeB.position.y), new Vector2(nodeB.position.x+20, nodeB.position.y), new Vector2(nodeB.position.x+10, nodeB.position.y+30)];
            hit = Collision.polygonPolygon(triA, triB);
            labelA.color = labelB.color = hit ? Color.RED : Color.GREEN;
        };
        tween(nodeB)
            .to(2, { position: nodeA.position.clone() }, { onUpdate: update })
            .call(() => {
                nodeA.removeFromParent(); nodeB.removeFromParent();
            })
            .start();
        update();
        this._show(parentNode, '2D多边形碰撞', true);
    }
    /** 2D批量圆碰撞测试（节点可视化） */
    static testBatchCircle(parentNode?: Node) {
        if (!parentNode) return;
        parentNode.removeAllChildren();
        const nodes: Node[] = [];
        const positions = [new Vector2(-60, 0), new Vector2(0, 0), new Vector2(60, 0)];
        const radii = [30, 30, 30];
        for (let i = 0; i < positions.length; i++) {
            const node = new Node('Circle'+i);
            node.layer = Layers.Enum.UI_2D;
            node.setPosition(positions[i].x, positions[i].y);
            const label = node.addComponent(Label); label.string = 'C'+i;
            label.fontSize = 18;
            label.color = Color.GREEN;
            parentNode.addChild(node);
            nodes.push(node);
        }
        // 检测所有圆对
        const pairs = Collision.detectAllCircleCollisions(positions, radii);
        for (const [i, j] of pairs) {
            nodes[i].getComponent(Label)!.color = Color.RED;
            nodes[j].getComponent(Label)!.color = Color.RED;
        }
        this._show(parentNode, '2D批量圆碰撞', pairs.length > 0);
    }
    /** 3D球体碰撞测试（节点可视化+缓动） */
    static testSphereSphere(parentNode?: Node) {
        if (!parentNode) return;
        parentNode.removeAllChildren();
        const nodeA = new Node('SphereA');
        const nodeB = new Node('SphereB');
        nodeA.layer = nodeB.layer = Layers.Enum.UI_2D;
        nodeA.setPosition(-60, 0); nodeB.setPosition(60, 0);
        const labelA = nodeA.addComponent(Label); labelA.string = 'SphereA';
        const labelB = nodeB.addComponent(Label); labelB.string = 'SphereB';
        labelA.fontSize = labelB.fontSize = 18;
        labelA.color = labelB.color = Color.GREEN;
        parentNode.addChild(nodeA); parentNode.addChild(nodeB);
        // 缓动B节点
        let hit = false;
        const update = () => {
            const a = new Vector3(nodeA.position.x, nodeA.position.y, 0);
            const b = new Vector3(nodeB.position.x, nodeB.position.y, 0);
            hit = Collision.sphereSphere(a, 30, b, 30);
            labelA.color = labelB.color = hit ? Color.RED : Color.GREEN;
        };
        tween(nodeB)
            .to(2, { position: nodeA.position.clone() }, { onUpdate: update })
            .call(() => {
                nodeA.removeFromParent(); nodeB.removeFromParent();
            })
            .start();
        update();
        this._show(parentNode, '3D球体碰撞', true);
    }
    /** 3D盒体碰撞测试（节点可视化+缓动） */
    static testBoxBox(parentNode?: Node) {
        if (!parentNode) return;
        parentNode.removeAllChildren();
        const nodeA = new Node('BoxA');
        const nodeB = new Node('BoxB');
        nodeA.layer = nodeB.layer = Layers.Enum.UI_2D;
        nodeA.setPosition(-60, 0); nodeB.setPosition(60, 0);
        const labelA = nodeA.addComponent(Label); labelA.string = 'BoxA';
        const labelB = nodeB.addComponent(Label); labelB.string = 'BoxB';
        labelA.fontSize = labelB.fontSize = 18;
        labelA.color = labelB.color = Color.GREEN;
        parentNode.addChild(nodeA); parentNode.addChild(nodeB);
        // 缓动B节点
        const size = new Vector3(60, 40, 40);
        let hit = false;
        const update = () => {
            const a = new Vector3(nodeA.position.x, nodeA.position.y, 0);
            const b = new Vector3(nodeB.position.x, nodeB.position.y, 0);
            hit = Collision.boxBox(a, size, b, size);
            labelA.color = labelB.color = hit ? Color.RED : Color.GREEN;
        };
        tween(nodeB)
            .to(2, { position: nodeA.position.clone() }, { onUpdate: update })
            .call(() => {
                nodeA.removeFromParent(); nodeB.removeFromParent();
            })
            .start();
        update();
        this._show(parentNode, '3D盒体碰撞', true);
    }
    /** 3D三角形碰撞测试（节点可视化+缓动） */
    static testTriangleTriangle(parentNode?: Node) {
        if (!parentNode) return;
        parentNode.removeAllChildren();
        const nodeA = new Node('TriA');
        const nodeB = new Node('TriB');
        nodeA.layer = nodeB.layer = Layers.Enum.UI_2D;
        nodeA.setPosition(-40, 0); nodeB.setPosition(40, 0);
        const labelA = nodeA.addComponent(Label); labelA.string = 'TriA';
        const labelB = nodeB.addComponent(Label); labelB.string = 'TriB';
        labelA.fontSize = labelB.fontSize = 18;
        labelA.color = labelB.color = Color.GREEN;
        parentNode.addChild(nodeA); parentNode.addChild(nodeB);
        // 缓动B节点
        let hit = false;
        const update = () => {
            const triA: [Vector3, Vector3, Vector3] = [
                new Vector3(nodeA.position.x, nodeA.position.y, 0),
                new Vector3(nodeA.position.x+20, nodeA.position.y, 0),
                new Vector3(nodeA.position.x+10, nodeA.position.y+30, 0)
            ];
            const triB: [Vector3, Vector3, Vector3] = [
                new Vector3(nodeB.position.x, nodeB.position.y, 0),
                new Vector3(nodeB.position.x+20, nodeB.position.y, 0),
                new Vector3(nodeB.position.x+10, nodeB.position.y+30, 0)
            ];
            hit = Collision.triangleTriangle(triA, triB);
            labelA.color = labelB.color = hit ? Color.RED : Color.GREEN;
        };
        tween(nodeB)
            .to(2, { position: nodeA.position.clone() }, { onUpdate: update })
            .call(() => {
                nodeA.removeFromParent(); nodeB.removeFromParent();
            })
            .start();
        update();
        this._show(parentNode, '3D三角形碰撞', true);
    }
    /** 3D多面体碰撞测试（节点可视化） */
    static testPolyhedronPolyhedron(parentNode?: Node) {
        if (!parentNode) return;
        parentNode.removeAllChildren();
        const nodeA = new Node('PolyA');
        const nodeB = new Node('PolyB');
        nodeA.layer = nodeB.layer = Layers.Enum.UI_2D;
        nodeA.setPosition(-40, 0); nodeB.setPosition(40, 0);
        const labelA = nodeA.addComponent(Label); labelA.string = 'PolyA';
        const labelB = nodeB.addComponent(Label); labelB.string = 'PolyB';
        labelA.fontSize = labelB.fontSize = 18;
        labelA.color = labelB.color = Color.GREEN;
        parentNode.addChild(nodeA); parentNode.addChild(nodeB);
        // 检测碰撞
        const vertsA = [
            new Vector3(nodeA.position.x, nodeA.position.y, 0),
            new Vector3(nodeA.position.x+20, nodeA.position.y, 0),
            new Vector3(nodeA.position.x+20, nodeA.position.y+20, 0),
            new Vector3(nodeA.position.x, nodeA.position.y+20, 0),
            new Vector3(nodeA.position.x, nodeA.position.y, 20),
            new Vector3(nodeA.position.x+20, nodeA.position.y, 20),
            new Vector3(nodeA.position.x+20, nodeA.position.y+20, 20),
            new Vector3(nodeA.position.x, nodeA.position.y+20, 20)
        ];
        const facesA = [
            [0,1,2,3],[4,5,6,7],[0,1,5,4],[2,3,7,6],[0,3,7,4],[1,2,6,5]
        ];
        const vertsB = vertsA.map(v => v.add(new Vector3(10,10,10)));
        const facesB = facesA;
        const result = Collision.polyhedronPolyhedron({vertices:vertsA,faces:facesA},{vertices:vertsB,faces:facesB});
        labelA.color = labelB.color = result ? Color.RED : Color.GREEN;
        this._show(parentNode, '3D多面体碰撞', result);
    }
    /** 3D批量球体碰撞测试（节点可视化） */
    static testBatchSphere(parentNode?: Node) {
        if (!parentNode) return;
        parentNode.removeAllChildren();
        const nodes: Node[] = [];
        const positions = [new Vector3(-60, 0, 0), new Vector3(0, 0, 0), new Vector3(60, 0, 0)];
        const radii = [30, 30, 30];
        for (let i = 0; i < positions.length; i++) {
            const node = new Node('Sphere'+i);
            node.layer = Layers.Enum.UI_2D;
            node.setPosition(positions[i].x, positions[i].y);
            const label = node.addComponent(Label); label.string = 'S'+i;
            label.fontSize = 18;
            label.color = Color.GREEN;
            parentNode.addChild(node);
            nodes.push(node);
        }
        // 检测所有球体对
        const pairs = Collision.detectAllSphereCollisions(positions, radii);
        for (const [i, j] of pairs) {
            nodes[i].getComponent(Label)!.color = Color.RED;
            nodes[j].getComponent(Label)!.color = Color.RED;
        }
        this._show(parentNode, '3D批量球体碰撞', pairs.length > 0);
    }
    /**
     * 显示测试结果
     */
    private static _show(parentNode: Node | undefined, label: string, ok: boolean) {
        if (!parentNode) return;
        const labelNode = new Node(label);
        labelNode.layer = Layers.Enum.UI_2D;
        const l = labelNode.addComponent(Label);
        l.overflow = Label.Overflow.RESIZE_HEIGHT;
        l.lineHeight = 24;
        l.fontSize = 18;
        l.string = `${label}: ${ok ? '通过' : '失败'}`;
        l.color = ok ? Color.GREEN : Color.RED;
        labelNode.setPosition(0, -60);
        parentNode.addChild(labelNode);
    }
} 